perm filename MCTCST.PUB[HAL,HE] blob sn#133595 filedate 1974-12-04 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00012 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.ctc: NEWSEC COMPILE-TIME CONSTRUCTS
C00005 00003	.pvs: NEWSS PLANNING VALUES
C00012 00004	.NEWSS PLANNING VARIABLES
C00015 00005	.NEWSSS ATOMS
C00019 00006	.NEWSSS |EXPRESSIONS, CLAUSES, STATEMENTS, AND FORMS|
C00024 00007	.asr:NEWSS ASSERTIONS
C00035 00008	.cex:NEWSS CONDITIONAL EXPANSION
C00042 00009	.NEWSSS BINDING BOOLEANS
C00045 00010	.newsss PICK
C00048 00011	.NEWSSS PLAN FOREACH
C00051 00012	.NEWSS	THE COMPILE-TIME CHECK STATEMENT
C00053 ENDMK
C⊗;
.ctc: NEWSEC COMPILE-TIME CONSTRUCTS

.NEWSS INTRODUCTION

AL seeks to maintain a fairly accurate planning model of the
expected state for each point in the execution of a program.  This
planning model includes the expected values of runtime variables,
together with a number of symbolic assertions about objects,
relations between frames, constraints on trajectory endpoint
conditions, and other information, and is important throughout the
system.  At the lowest level, it provides "target" locations for the
calculation of proper trajectories.  Beyond this, planning
information is used to direct conditional expansion of input programs
and library routines, and provides a basis for decisions on how to
translate the various high-level, assembly-oriented constructs into
runnable manipulation programs. 

A number of language constructs are provided in AL to allow the user
to access this model and to assist in maintaining it.  These
facilities are described in this chapter, which also discusses
language features such as conditional compilation for increasing the
convenience of programming and the flexibility of programs.  The use
of the planning model facilities for object descriptions and by the
"very high level" components of AL is discussed more fully in {secref vhl}. 

.pvs: NEWSS PLANNING VALUES

One very important piece of information about a variable
is its %4planning value%*, which is the compiler's estimate of what value
the variable will have at some point in the program execution.
As with other aspects of the planning model, planning values have
many uses in AL.  One especially important use is in trajectory
calculation.  Although provisions are made to modify any preplanned
trajectory before executing it, the current scheme requires that
at least a roughly accurate value be available at compile time if
smooth trajectories are desired.  This was discussed in {sssref mrt}.

Typically, planning values are updated whenever the compiler encounters
something that it has reason to expect will cause the runtime value to 
change.  For instance, the assignment statement
.unfill
	foo ← 3
.refill
will cause the compiler to emit code to set foo to 3 and will cause it to
change the planning value of foo to become 3.  Similarly
.unfill
	a ← b + c
.refill
will cause the planning value of variable %4a%* to be set to the planning value
of %4b%* plus the planning value of %4c%*, provided that both %4b%* and %4c%* have
known planning values.  If one of the planning values isn't known, then
%4a%* gets the special planning value %4undefined%*,
 which is also used as an initial
planning value at the time a variable is declared.

 Motion statements also
can cause planning values to be updated.  For instance, 
.unfill
	MOVE yellow TO bar
.refill
will cause the planning value of yellow to be set to the planning
value of bar.  Also, the planning value of any variables affixed to
yellow will be updated appropriately.

The planning value of a variable may be retrieved by use of the construct
.unfill
	α#(<variable name>)
.refill
which yields a constant equal to the planning value of the variable.
For example,
.unfill
	b ← 3;
	a ← α#(b);

.bull
has the same effect as

	b ← 3;
	a ← 3;
.refill
Although the compiler makes an effort to keep track of the expected
runtime state of variables,  it must sometimes be given explicit
assistance.  For example, it is difficult for the compiler to
maintain unambiguous planning values over conditional statements, as in
this example:
.unfill
	SCALAR s1, s2;
	VECTOR v1;
	s1 ← 100;
	IF s2 > 3 THEN
		BEGIN
		v1 ← VECTOR(1,2,3);
		s1 ← 101;
		α{α#(s1) = 101α}
		α{α#(v1) = VECTOR(1,2,3)α}
		END
	ELSE
		BEGIN
		v1 ← VECTOR(1,2,4);
		α{α#(v1) = VECTOR(1,2,4)α}
		α{α#(s1) = 100α}
		END;
	α{α#(v1) = UNDEFINEDα}
	α{α#(s1) = UNDEFINEDα}
.refill
Although the compiler may eventually be smart enough to resolve a
number of such cases, for the moment the user must tell the compiler
what planning value to use thereafter.  

The compile-time assignment statement:
.unfill
	<variable> ←← <constant expression>
.refill
is provided to set the planning  value of a variable.  Such assignments
affect only the planning value;  no code is emitted, and the runtime
value of the variable remains unaffected.  Thus, both
.unfill
	v ← VECTOR(3,3,3)
.bull
and
	v ←← VECTOR(3,3,3)
.refill
set the planning value of %4v%* to VECTOR(3,3,3), but only the
first form causes the runtime value of %4v%* to be changed.

Planning values provide a useful way to generate error estimates,
as in
.unfill
	FRAME f1, f2, f3;
	:
	AFFIX f1 TO f2 RIGIDLY;
	:
	AFFIX f2 TO yellow;
	MOVE yellow TO f3;
.comt 12
	α{Moving the yellow arm will cause the runtime values of frames
	f1 and f2, which are affixed to it, to be updated as well.α}
.end
	WHILE ABS(LOC(f1)-LOC(α#(f1))) > .25*CM DO
		BEGIN
		:
		α{%4Make a correction%*α}
		α{%4Measure f1%*α}
		:
		END;
.refill
Although it is theoretically possible for the user
to fill in the relevant nominal values explicitly, in practice this
can be rather inconvenient, especially when the planning values are
derived from some complicated computation.  Furthermore, the availability
of planning values
offers significant advantages with regard to program flexibility, since
changing a particular expected value will not, in general, require 
substantial changes in program text.

.NEWSS PLANNING VARIABLES

Planning variables allow the user to take advantage of the
compile-time computation and planning value maintenance facilities
of AL without incurring the runtime overhead of having regular
variables in cases where only their planning values are ever used. 
Typical uses include attaching symbolic names to constants,  use of temporary
variables in compile-time calculations, object modelling, access to
symbolic assertions in the planning model, passing "advice" to
high-level language primitives and to library routines. 

.newsss |ALGEBRAIC PLANNING VARIABLES|

Algebraic planning variables are declared by the construct
.unfill
	PLANNING <data-type> <identifier 1>, ... , <identifier n>   .
.bull

For instance,

	PLANNING SCALAR a, b, c;
	PLANNING DISTANCE SCALAR d1, d1;
	PLANNING FORCE VECTOR f1, f2, lift;
	PLANNING TRANS t;
.refill
Such variables may have planning values, but have no runtime existence
whatsoever.  This means that they may appear on the left hand side of
planning assignment statements (i.e., the "α←α←" form), but not 
of regular assignment statements (i.e., the "α←" form).  Similarly,
a planning variable may not appear in an arithmetic expression,
although its planning value (that is, α#(<ct#var>) ) may do so.  Thus,
the following are legal:
.unfill
	PLANNING SIMPLE a, b;
	SIMPLE v;

	a ←← 3;
	b ←← α#(a) - .01;
	v ← 2 + α#(a);
	v ← α#(v) - v*α#(b);
	b ←← UNDEFINED; α{%4this causes b to lose its planning value%*α}
.bull

These, however, are not legal:

	PLANNING SIMPLE a, b;
	SIMPLE v;

	a ← 3;
	v ← a; α{%4Note that no coercions to planning values are ever made.%*α}
	b ← a; α{%4Ditto%*α}
	v ← UNDEFINED; α{%4UNDEFINED has no runtime meaning.%*α}
.refill	

.NEWSSS ATOMS

In addition to the regular runtime data types, there are several
additional types that (presently) can occur only with planning
variables.  These variables follow the usual rules concerning
planning value assignment and propagation, except that their "value" is
not an arithmetic quantity.  Instead, it is the internal structure
associated with some construct in the language.  Perhaps the most
important of these variable types is the %4atom%*, which is a variable
whose (planning) value is the name of another variable.
Atoms are declared by the construct
.unfill
	ATOM <id1>, ... , <idn>;
.refill
Note that the word "PLANNING" is not needed, since an atom is purely a
planning construct.
Planning values may be assigned to atom variables by use of the construct
.unfill
	<atom name> ←← <variable name>
.bull
as in

	ATOM a1, a2, a3;
	DISTANCE SCALAR d;

	a1 ←← d;
	a2 ←← a3;
	α#(a2) ←← α#(a1);
.COMT 12
	α{Now, α#(a1)="d", α#(a2)="a3", α#(a3)="d"α}
.end
.refill
Notice that α#(<atom>) yields the name of a variable; its effect is
as if the variable itself were used.  Thus, 
.unfill
	d ← 100*feet
.bull
and

	α#(a1) ← 100*feet
.refill
will both have the same effect.  Also, note that assignment to an atom
constitutes the only case where the name of a variable may appear on the
right hand side of a planning assignment statement.

Atoms serve a number of useful purposes, the most prominent of which
include serving as "key words" in symbolic assertions, providing a means
for retrieving and using variables as object properties, and 
as a means for adapting the same piece of program text to perform
different versions of the same task.  For instance,
.unfill
	ATOM arm, h;
	FRAME hole1,hole2;
	:
	arm ←← blue;
	h ←← hole1;
	:
	MOVE α#(arm) TO α#(h);
	:
	h ←← hole2;
	:
	MOVE α#(arm) TO α#(h);
	:
.refill
Here, the MOVE statement has been typed out twice, so the actual saving
is rather small.  In practice, however, it is common to place such statements
inside a macro or library routine (see {ssref lib}), in which case the 
gain in convenience can be appreciable.  Similarly, the atoms "arm" and "h"
can be given planning values by means of the BIND construct in a planning
conditional expansion (see {ssref cex}).
.NEWSSS |EXPRESSIONS, CLAUSES, STATEMENTS, AND FORMS|

Another very important
type is the %4expression%*, which takes as its planning value the internal
structure associated with an expression in the language.  These variables
are declared by the construct
.unfill
	EXPRESSION <id1>, ... ,<idn>;
.refill
Again, note that the word "PLANNING" is not used.  If desired,
an atom or expression variable may be restricted to values of some particular
algebraic
type by inclusion of the appropriate additional declarators.  For instance,
.unfill
	DISTANCE ATOM da;
	VECTOR ATOM va;
	FORCE VECTOR ATOM fva;
	TRANS EXPRESSION te1, te2;
.refill

Other planning only types include %4statement, clause,%* and %4form%*.
Statement variables
take as their planning values the internal structure associated with a statement.
Clause variables take as their planning values the structure associated with
clauses, such as "TO#⊗" and "WITH#DURATION#≥#3*SEC".
Clauses, statements and expressions are primarily useful as a means of passing explicit
"advice" on to a library routine or high-level primitive.  In addition,
statement variables are frequently very useful as placeholders in partially
written code.

%4Form%* variables hold references to assertions in the compiler's planning
model and are discussed in more detail in subsequent sections.  One use
is to allow a user to remember the name of an assertion in such a way
as to facilitate undoing it later.

Planning values may be assigned to clause, statement, expression, and form variables
by use of the appropriate construction functions to produce constants
of the appropriate types.  Thus we might have:
.unfill
	TRANS t1;
	FRAME widget;
	ATOM height;
	CLAUSE c;
	EXPRESSION e;
	STATEMENT s;
	FORM f;
	:
	f ←← FORM(height, widget, 100);
	e ←← EXPRESSION(t1*ypark);
	s ←← STATEMENT(MOVE YELLOW TO α#(e));
	c ←← CLAUSE(VIA widget);
.comt 12
	α{Note that α#(e) will not be evaluated until the planning
	value of s is used; that is, until α#(s) is used as a statement somewhereα}
.end
.refill
As one might expect, the argument to an %4expression%* primitive is an expression,
the argument to %4clause%* is a clause, and
and the argument to a %4statement%* primitive is a statement.  These compile-time
functions return the internal structures associated with their arguments; when
this structure is stored into a planning variable of the appropriate type
then the planning value of that variable becomes the expression or statement.
Thus, 
.unfill
	e ←← EXPRESSION(t1*t2*f1);
	c ←← CLAUSE(VIA widget);
	s ←← STATEMENT(MOVE YELLOW TO f3 α#(c));
	:
	f3 ← α#(e) 
	α#(s);
.bull
and
	f3 ← t1*t2*f1;
	MOVE yellow TO f3 VIA widget;
.refill
will have exactly the same effect.

.asr:NEWSS ASSERTIONS

In addition to planning values, the planning model used by AL
includes a number of facts that are usefully expressed as symbolic
assertions.  These facts include object descriptions, semantic information
about what is in the hands, state information about required approaches
for motions,and relations between frames.  Internally, all facts
(whether added to the data base by the compiler or explicitly by the
user) are represented as forms of constant elements
such as one might find as planning values for some variable or another.
For example,
.unfill
	FORM(Roses, are, red);
	FORM(WEIGHT, engine_block, 3.5*POUNDS);
	FORM(AFFIXED, f1, TO, f2, BY, t3, RIGIDLY);
	FORM(v1, COMPUTED_BY, EXPRESSION(a*v2+v3) );
.refill
are typical of the sort of forms which one might have in the data base.

Readers familiar with recent research in artificial intelligence will 
no doubt recognize the similarity of many of the constructs presented in this
section with comparable features in modern AI languages.  A detailed
discussion of this relation or of implementation details is beyond the
scope of this paper.  However, perhaps it should be pointed out again
that the assertion mechanisms in AL are a planning-time construct without
any runtime existence.  The system attempts to keep track of what facts are
expected to be true at each point in the program by associating with each
fact in the data base a set of "worlds" corresponding to each place that
a fact is true.  Some further discussion of this mechanism may be found in
{SSREF wld}.

.NEWSSS THE ASSERT STATEMENT

Symbolic assertions may be added to the data base by use of the statement
.unfill
	ASSERT <form>
.refill
where <form> is either the planning value of a FORM variable or a call
on the FORM construction primitive,
.unfill
	FORM(<element 1>,<element 2>, ... ,<element n>)
.refill
In general, each <element> must be something that can appear on the right
hand side of a planning assignment statement (i.e., the "α←α←" assignment).
This includes constants, expressions involving only constants (including
α#(<variable>) ), variable names, and the results of construction functions
like EXPRESSION, STATEMENT, and FORM.  (Also, the BIND construct is allowed,
but this is discussed later).  For instance,
.unfill
	ATOM holds, SLOT, headtype1, HEX, now, is, the, time;
.COMT 12
	α{We are following a convention that %*individuals%4 are
	in lower case, and %*classes or properties%4 are in upper
	case.α}
.END
	STATEMENT PARKING_METHOD;
	FRAME driver1;
	FORM formvar;
	:
	ASSERT FORM(yellow, holds, driver1);
	ASSERT FORM(SLOT, headtype1, HEX, 0.53);
	ASSERT FORM(PARKING_METHOD, yellow,
			STATEMENT(MOVE YELLOW TO YPARK));
	formvar ←← FORM(now, is, the, time);
	ASSERT α#(formvar)
.refill
The actual meaning of an asserted pattern is  generally determined by
whatever conventions the user may  wish to establish.  However, a few
pattern types, such as those for affixment or those used by the very
high level  routines for  object descriptions,  are "understood"  and
used  by the  compiler.  (As mentioned earlier, AL includes a number
of predeclared atoms to act as key words in these reserved patterns.)
The  user can  cause serious  confusions by
improper  introduction  or  deletion  of  such  patterns, although,
used properly, they provide a valuable tool for communication with the
planning model.

.NEWSSS THE DENY STATEMENT

Generally,
assertions will  remain "true"  in the  compiler's world  model until
explicitly  deleted  or,  in  the  case  of  assertions  used by  the
compiler,  as  a  side  effect  of  processing  some  statement.  Any
assertion may be undone by use
of the DENY construct, which is similar to ASSERT:
.UNFILL
	DENY FORM(IN, HAND, screwdriver);
	DENY α#(formvar);
.REFILL

.NEWSSS CONSTRAINT ASSERTIONS

In addition to planning values and symbolic assertions, the system's
planning model may include constraint information delimiting the
range of values that a variable may take on.  Much of this
information is expressed internally by means of mathematical
constraints on scalar variables that represent degrees of freedom in
object locations. 
For instance, if a flat surface of an object is flush up
against another flat surface, then (in the absence of other
constraints) the object will have two translational and one
rotational degrees of freedom.  
These constraints are generally derived from the semantics of the
various "high level" operations, the object descriptions, and 
certain "standard" assertional patterns. (See {ssref var} for more
details.)  In addition, however, a user can use the construct
.unfill
	ASSERT <expression><relation><constant>
.refill
in order to state a constraint relationship explicitly.  
The <relation> may be any of "≤","<","=",">", and "≥".  At present,
<expression> is restricted to be a linear form involving only scalar
variables or the dot product of two vectors.  For instance,
.unfill
	DISTANCE SCALAR a, b, c;
	VECTOR v;
	:
	ASSERT 3*a + 4*b - 2*c  ≤  2*INCHES;
	ASSERT v . Z > 0.25;
.refill	
This construct is primarily intended for use in debugging the higher
level operators and in writing library routines that are to be
used with such operators.  It is being described here in the interests
of completeness and because reference is made to it in {ssref var}.


.NEWSSS STANDARD USES FOR ASSERTIONS

The user may use the assertional database to store arbitrary information.
Certain patterns, however, are given special meaning in AL.  For example,
in our discussion of deproaches, we implied that the compiler keeps track
of each frame's associated deproach by means of assertions.  Thus, to
give the frame f1 a deproach transformation t1, one writes:
.unfill
	ASSERT FORM(DEPROACH, f1, t1)	.
.refill
Another standard use is for affixments.  One effect of the statement
.unfill
	AFFIX f1 TO f2

.bull
is the assertion

	ASSERT FORM(AFFIXED, f1, f2)	.
.refill
Similarly, the object descriptions used by the assembly-oriented operations,
as well as the planning model associated with such operations, rely quite
strongly on standard assertion patterns.
A fuller discussion of some of these patterns may be found in {ssref obd}.
However, this document does not purport 
to list fully all the patterns that are actually used by AL, although
it should give the reader some idea of their approximate extent and
should provide a fair indication of how they are actually used.
.cex:NEWSS CONDITIONAL EXPANSION

It is frequently desirable to write a  fairly general piece of source
code that produces  different object code,  depending on the specific
task to  be performed and  on the  compiler's model  of the  expected
runtime  environment.

.NEWSSS PLAN IF

   The  principal  mechanism  provided for  this
purpose is the plan-time conditional construct, which behaves like
a conventional Algol  "IF",   except that it  is resolved at  compile
time,   with only the  the "expanded" part  having any effect  on the
compiler's world model.  The syntax is:

.UNFILL
	PLAN IF <condition> THEN
		<then-part>
	ELSE 
		<else-part>
.REFILL
where the "ELSE" component may be omitted  if desired.  The condition
may  be  any  boolean  expression  which can be completely evaluated at
plan-time.  For instance:
.UNFILL
	PLAN IF α#(blue) ≠ bpark THEN
		MOVE blue TO bpark;
.REFILL
which says that if the planning value of the blue arm is not equal to
bpark (that is, if the last motion statement for the blue arm was not
to its parked position), then insert a statement to move it there.
Similarly, suppose we have a general routine for putting screws in
holes.  Further, assume that we are using a plan-time variable
"chamfer" to contain the width of chamfering around the hole.  Then
the routine might have something like:

.UNFILL
	PLAN IF α#(chamfer) > .25*INCHES THEN
		BEGIN
.COMT 16
		α{Code to perform a simple "straight in" insertionα}
.end
		END
	ELSE 
		BEGIN
.comt 16
		α{Code to perform some sort of a search to 
			get the screw into the holeα}
.end
		END;

.REFILL

.NEWSSS TESTING FOR ASSERTIONS

The presence in the data base of a symbolic form can be tested by use
of the %4asserted%* construct, as in
.UNFILL
	PLAN IF ASSERTED(FORM(IN,TOOLRACK,SCREWDRIVER)) THEN
		BEGIN
.COMT 16
		α{Code to fetch the screwdriver out
		        of the tool rackα}
.END
		END;
.bull
In general,

	ASSERTED(<form>)
.refill
returns "true" whenever the <form> is asserted in the planning model
at the point that the test is made.  Thus,
.unfill
	FORM f;
	TIME t;
	:
	PLAN IF ASSERTED(α#(f)) THEN
		BEGIN
		t←3*SEC;
		DENY α#(f);
		END;
	PLAN IF ASSERTED(α#(f)) THEN
		BEGIN
		t←4*SEC;
		END;
	:
.bull
would expand into 

	FORM f;
	TIME t;
	:
	t←3*SEC;
	DENY α#(f);
	:
.refill
Furthermore, note that ASSERTED(<form>) acts like a boolean primary and
can enter into boolean expressions in the usual way.  For instance,
.unfill
	PLAN IF ASSERTED(FORM(GOES_IN,shaft1,hole1))
			∧¬ASSERTED(FORM,IN,shaft1,hole1)) THEN
		BEGIN
		PLAN IF ASSERTED(FORM(THREADED,shaft1)) THEN
			BEGIN
.COMT 20
			α{code to insert a threaded screwα}
.END
			ASSERT FORM(SCREWED,shaft1);
			END
		ELSE
			BEGIN
.COMT 20
			α{code to insert a smooth pinα}
.END
			ASSERT FORM(SLIPPED_IN,shaft1);
			END;
		ASSERT FORM(IN,shaft1,hole1);
		END;
.REFILL

.NEWSSS THE ANYTHING CONSTRUCT

Frequently, one may want  to test a whole class of  asserted forms at
once. For  instance, suppose we may want to know  if the blue hand is
available for some task or another.  We can keep track of what  is in
the hand by means of assertions like
.UNFILL
	ASSERT FORM(blue,HOLDS,widget);
.REFILL
However, it  is frequently inconvenient,   and  sometimes impossible,
to test all possibilities explicitly, as in:
.UNFILL
	PLAN IF ¬ASSERTED(FORM(BLUE,HOLDS,widget))
	    ∧ ¬ASSERTED(FORM(BLUE,HOLDS,frob)) ∧ . . .  THEN
			BEGIN
			α{%4whatever%*α}
			END;
.REFILL

The reserved word ANYTHING  is provided as a wild card  to avoid this
difficulty.  Thus, we can write:
.UNFILL
	PLAN IF ¬ASSERTED(FORM(BLUE,HOLDS,ANYTHING)) THEN
		BEGIN
		α{%4whatever%*α}
		END;
.REFILL
One restriction of the current implementation is that one is not allowed
to assert forms containing wild card elements like ANYTHING or the
BIND construct discussed in the next section.  One can only use them in
constructs like ASSERTED, which don't try to add anything to the data base.

.NEWSSS BINDING BOOLEANS

Frequently a simple wild card element like ANYTHING does not suffice.
For example,
the  user may want  to execute different  code, depending  on what is
supposed to be in the  blue hand.  This situation is provided for by
the use of 
.unfill
	BIND(<ct variable>)
.refill
as one or more of the elements in a FORM pattern being tested by the ASSERTED
construct.   Generally, BIND(var) acts like a "wild card" that matches
any element in the correct position in a form that has the same type as
var.  It has the additional side effect of setting the planning value
of var to be the value of the element it matched.  For example,
.UNFILL
	ATOM thing;
	PLANNING FRAME where;
	:
	ASSERT FORM(blue,HOLDS,frob);
	ASSERT FORM(CORRECT_SPOT_FOR,frob,FRAME(ROT(Y,180),VECTOR(1,2,3)) );
	ASSERT FORM(CORRECT_SPOT_FOR,widget,
					FRAME(ROT(Y,180),VECTOR(4,5,6)) );
	:
	PLAN IF ASSERTED(FORM(blue,HOLDS,BIND(thing)) ) THEN
		BEGIN
		α{%4Here, α#(thing) will get "FROB"%*α}
		IF ASSERTED(FORM(CORRECT_SPOT_FOR,α#(thing),BIND(where))) THEN
			BEGIN
			MOVE blue TO α#(where);
			α{%4some more code%*α}
			END
		ELSE
			BEGIN
			α{%4some sort of error message, perhaps%*α}
			END;
		END;

.bull
Would expand into

	MOVE blue TO FRAME(ROT(Y,π*RAD),VECTOR(1,2,3));
	α{%4some more code%*α}
.REFILL
This construct is especially useful for library routines, which can use
it to retrieve properties of objects and then take appropriate action.

.newsss PICK

One frequent use of assertions in to specify a number of properties of some
object or variable.  For instance,
.UNFILL
	ASSERT FORM(HEIGHT,widget,100*CM);
	ASSERT FORM(WEIGHT,widget,200*GM);
	ASSERT FORM(DEPROACH,widget,FRAME(ROT(Y,π*RAD),X));
.REFILL
These properties can, of course, be retrieved by means of the ASSERTED
construct, as in
.unfill
	PLAN IF ASSERTED(FORM(HEIGHT,widget,BIND(h)) )  THEN
		BEGIN
		MOVE YELLOW TO widget + α#(h);
		:
		END
	ELSE
		BEGIN
		α{%4perhaps some sort of error message%*α}
		END
.refill
Unfortunately, this sort of thing can be rather inconvenient for 
fetching values, since  it requires explicit use of an auxiliary
variable and a fairly long statement.  In such cases the PICK construct
can be used instead, as in 
.unfill
	MOVE yellow TO widget + PICK(FORM(HEIGHT,widget,BIND(*)) )
.refill
In general, PICK has the form
.unfill
	PICK(<form pattern>)
.refill
where the <form pattern> contains "BIND(*)" as %4one%* of its terms.  PICK
causes the compiler to retrieve a form that is in the planning model
and which matches the template provided by the <form#pattern>.  The 
value in the form from the data base corresponding to the "BIND(*)" term 
in the template pattern is then returned as the value for PICK.
Note that the argument template can also contain additional instances
of ANYTHING and BIND(<variable>).  These are bound in the usual way.
For instance,
.unfill
	ASSERT FORM(gadget,fits,onto,widget,at,FRAME(NILROT,X) );
	:
	obj ←← PICK(FORM(gadget,fits,onto,BIND(*),ANYTHING,BIND(locn)) );
.refill
would set the planning value of obj to "widget" and that of locn to
FRAME(NILROT,X).

.NEWSSS PLAN FOREACH

Sometimes, there may be several assertions in the data base that could
satisfy a given FORM retrieval pattern.  For instance,
.UNFILL
	ASSERT FORM(s1,SCREWS,INTO,h1);
	ASSERT FORM(s2,SCREWS,INTO,h2);
	ASSERT FORM(s3,SCREWS,INTO,h3);
	:
	PLAN IF ASSERTED(FORM(BIND(s),SCREWS,INTO,BIND(h))) THEN
		BEGIN
		:
		END
.REFILL
In  such cases,  the  compiler  would  arbitrarily pick  one  of  the
eligible  patterns  to  use  as  its  template for  performing  any
requested bindings.  Suppose, however, that the user wants to perform
some action for %4each%* pattern that matches, rather than  for only one.
For  instance, he  may want  to  insert all  the  screws  into their
corresponding holes.  The PLAN FOREACH construct is intended
to allow this sort of thing.
.UNFILL
	PLAN FOREACH <form> DO
		 <statement>
.REFILL
This construct will cause <statement> to be compiled once for each 
instance of <pattern> that finds a match in the data base.

For instance, a library routine that fastens down a head to an engine
block by means of bolts which can be inserted in any order might
include a sequence like:
.UNFILL
	ATOM bolt, hole_id, head_id;
	:
	PLAN FOREACH FORM( BIND(bolt),FASTENS,α#(head_id)) DO
		BEGIN
		PLAN IF ASSERTED(FORM(α#(bolt),FITS,INTO,BIND(hole_id))) THEN
			INSERT α#(bolt) INTO α#(hole_id)
		ELSE 
			BEGIN
			PLAN ERROR(bolt,"doesn't fit into",hole_id);
			END;
		END;

.bull
If we then have assertions:

	ASSERT FORM(b1,FASTENS,pumphead);
	ASSERT FORM(b2,FASTENS,pumphead);
	ASSERT FORM(b3,FASTENS,pumphead);
	ASSERT FORM(b1,FRITS,INTO,h1);
	ASSERT FORM(b2,FITS,INTO,h2);
	ASSERT FORM(b3,FITS,INTO,h3);
.REFILL
and call our library  routine to put on pumphead,  the above fragment
would expand into 
.UNFILL
	INSERT b1 INTO h1;
	INSERT b2 INTO h2;
	INSERT b3 INTO h3;
.REFILL

.NEWSS	THE COMPILE-TIME CHECK STATEMENT

	Since library routines will be commonly used, it is necessary
to have some  way of checking that necessary preconditions are met as
the first steps of the library routine.  The way this is done is with
the %4check%* statement.  A simple example:
.unfill
	CHECK  α#(s1)=3 ∧ α#(s2)>5
.refill
   The  contents of  the check  may be  any
boolean expression,  including checks on the current world model. The
check is only  made at compile-time; if  the check is not  satisfied,
the compiler will generate an error message.
The effect of this statement is exactly like that of
.UNFILL
	PLAN IF ¬(α#(s1)=3 ∧ α#(s2)>5 THEN
		PLAN ERROR("Check statement failed")   .
.REFILL